home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
vdl020d.zip
/
HM.DOC
< prev
next >
Wrap
Text File
|
1993-04-14
|
39KB
|
911 lines
(*
==================== H A C M A N A G E R U N I T ====================
= =
= Version 1.0.0 06/03/92 Jon Taylor =
= =
==========================================================================
= =
= Hac Manager library for TP V:6.0 =
= =
= Written By Jonathan Robert Taylor =
= =
= This code is the property of Columbia Data Products, Inc. =
= It may be distributed and used outside CDP so long as this header =
= remains intact and unmodified, and as long as it is used with a =
= licensed Columbia Data Products, Inc. product. =
= =
= Copyright 1991,1992 Columbia Data Products =
= ALL RIGHTS RESERVED =
= =
==========================================================================
= =
= Revision History Procedures changed; overall purpose of change.=
= Procedure specific revision notes below. =
= Reverse chronological order. =
= ---------------------------------------------------------------------- =
= date initials change description =
= ---------------------------------------------------------------------- =
= =
= 11-19-92 jrt Modified HM_ExecSCSI to poll locally instead =
= of making HAC poll. =
= =
= 06-03-92 jrt Tested. Modified to use Hac Manager 0.5.0 =
= =
= 05-18-92 jrt Added code to turn interrupts off before executing =
= critical or non-reentrant code. =
= =
= 05-13-92 jrt All code written, no testing yet. =
= =
= 05-05-92 jrt Started =
= =
==========================================================================
= =
= Caveats =
= ---------------------------------------------------------------------- =
= date initals description =
= ---------------------------------------------------------------------- =
= =
= 06-03-92 jrt May need to pass actual CDB to HM_ExecSCSI instead =
= of a pointer, so that the memory for the CDB =
= doesn't have to exist in two places (packet&Heap) =
= =
= Need to clean up HM_ExecSCSI usage of physical IOS =
= /virtual IOS/auto addressing =
= =
= We currently create the CAPS data locally, as =
= the HAC manager does not yet return all the =
= necessary information (version, OSDP size, etc) =
= =
= HM_PacketAbort and HM_ReqSenseBroadcast are not =
= yet completed, as they are not properly =
= implemented in the HAC manager. =
= =
= The internal function CallHacManager makes =
= provisions for the HAC manager returning a =
= value in AX. The Hac manager does not return a =
= value in AX, so the value returned by =
= CallHacManager is hardcoded to 0. =
= =
==========================================================================
*)
Unit HM;
Uses
DOS;
Const
eInit_NoHacManager = $01;
eIOSAdd_IOSFull = $01;
eExecSCSI_CantAlloc = $FFFF;
eXS_CantAlloc = $FFFF;
eXS_OK = $8100;
{----------------------}
{ HAC Manager Commands }
{----------------------}
HCMD_ExecCDB = $00;
HCMD_HacInit = $01;
HCMD_ResetBus = $02;
HCMD_ResetDev = $03;
HCMD_Raw = $04;
HCMD_Abort = $05;
HCMD_VtoP = $F5;
HCMD_ClearVtoP = $F5;
HCMD_AEN_Sense = $F7;
HCMD_RemoveHac = $F8;
HCMD_RemoveClient = $F9;
HCMD_GetClient_ID = $FA;
HCMD_AddClient = $FB;
HCMD_SetHDT = $FC;
HCMD_GetHDT = $FD;
HCMD_GetNum_Hacs = $FE;
HCMD_AddHAC = $FF;
{------------------}
{ Hac Packet Flags }
{------------------}
HFLG_Poll = $0001; { Dont return until HAC CMD is done }
HFLG_Write = $0002; { SCSI Write operation }
HFLG_Read = $0000; { SCSI Read operation }
HFLG_NoBusyRetry = $0004; { No retries on busy }
HFLG_AutoDir = $0008; { Do Auto direction determination }
HFLG_AutoAddr = $0010; { Do auto address conversion }
HFLG_StopOnLinkErr = $0040; { Stop linked commands on an error }
HFLG_PascalPost = $0080; { Post with pascal stack frame }
HFLG_VtoPClear = $8000; { Clear the Virt to Phys convert }
HSTAT_NotDone = $00; { Command In Progress }
HSTAT_Success = $01; { Command Compleate With No Error }
HSTAT_ScsiError = $02; { Cmd Compleate With SCSI Error }
HSTAT_HacFailed = $03; { General Hac Failure }
HSTAT_IRQCnflct = $04; { Interrupt Line Conflict }
HSTAT_CmdTimeOut = $05; { Command Timeout }
HSTAT_Busy = $06; { HAC Is Busy }
HSTAT_DevNotResp = $07; { Selection Timeout }
HSTAT_BusReset = $08; { SCSI Bus Was Reset }
HSTAT_HMTD = $09; { Host Has More Data Than Trg Wants }
HSTAT_HLTD = $0A; { Host Sent Less Data Than Trg Wants}
HSTAT_TMHD = $0B; { Trg Has More Data Than Host Wants }
HSTAT_TLHD = $0C; { Trg Sent Less Data Than Host Wants}
HSTAT_BadSense = $0D; { Failed To Get sense Data }
HSTAT_BadCmd = $0E; { Bad Hac Command Code Sent }
HSTAT_BadPhase = $0F; { Bad Bus Phase Detected }
HSTAT_CmdAbrted = $10; { HAC Command Aborted }
HSTAT_NoAutoDir = $11; { No Auto Direction Allowed }
HSTAT_HDTCnflct = $12; { HAC Rejected Due To HDT Conflict }
HSTAT_HACMgrFull = $13; { Maximum Number Of HACs Reached }
HSTAT_BadHac = $14; { Bad HAC Number Specified }
HSTAT_BadSubChnl = $15; { Bad SubChannel Specified }
HSTAT_NoHACMgr = $16; { No HAC Manager Installed }
HSTAT_BadAddr = $17; { Bad Address Passed }
HSTAT_BadClient = $18; { Bad Client Number Specified }
HSTAT_CrdNotResp = $19; { Host Adapter Not Responding }
HSTAT_BadHACRp = $1A; { Invalid Field In HAC Request Pkt }
HSTAT_MaxClients = $1B; { Max Client Reached, Client Reject }
HSTAT_VtoPFailed = $1C; { Virtual To Physical Failed }
HSTAT_VtoPClrFail = $1D; { Virtual To Physical Clear Failed }
HSTAT_NoTermPower = $1E; { No Termination Power On SCSI Bus }
HSTAT_HDTModify = $1F; { HDT Was Modified To Cards Values }
HSTAT_BadFirmware = $20; { Unsupported Firmware }
HSTAT_DEVST_VALID = $21; { Device status Is Valid }
{--------------------------}
{ IOS Allocation Constants }
{--------------------------}
IOS_AllocPhys = $01; { Alloc a Physical IOS }
IOS_AllocVirt = $02; { Alloc a Virtual IOS }
IOS_AllocDefault = $04; { Alloc with default # of entries }
{----------------------------}
{ HM_ExecSCSI Flag Constants }
{----------------------------}
ES_Poll = $0001;
ES_Write = $0002;
ES_Read = $0000;
ES_NoBusyRetry = $0004;
ES_AutoDir = $0008;
ES_PascalPost = $0080;
ES_CPost = $0000;
ES_UseIOSH = $8000;
{-----------------------------------}
{ ESDefaultPostInfo Structure Flags }
{-----------------------------------}
ESDP_Complete = $01;
Type
T4Byte = Array[0..3] of BYTE;
TError = WORD;
TAENHandle = WORD;
{-----}
{ CDB }
{-----}
TCDB = Array[1..16] of BYTE;
PCDB = ^TCDB;
{---------------}
{ Data Buffer }
{---------------}
TData = Array[0..0] of BYTE;
PData = ^TData;
{--------------------}
{ Hac I/O Structure }
{--------------------}
TIOSEntry = Record
Addr : Pointer;
Size : LONGINT;
END;
PIOSEntry = ^TIOSEntry;
TIOS = Array[1..128] of TIOSEntry;
PIOS = ^TIOS;
PPIOS = ^PIOS;
TIOSHeader = RECORD
Avail : WORD;
Used : WORD;
IOS : PIOS;
END;
PIOSHeader = ^TIOSHeader;
{--------------------}
{ Hac Command Packet }
{--------------------}
PHacPacket = ^THacPacket;
THacPacket = RECORD
Command : BYTE;
flagw : WORD;
Target : BYTE;
LUN : BYTE;
Channel : BYTE;
SubChannel : BYTE;
DevStatus : BYTE;
HacStatus : BYTE;
CDBSize : BYTE;
CDB : TCDB;
SenseBuff : Pointer;
SenseBuffSize : WORD;
VueStatus : Pointer;
IOSize : LONGINT;
PhysElements : WORD;
PhysIOS : PIOS;
VirtElements : WORD;
VirtIOS : PIOS;
PostRoutine : Pointer;
PostDataSeg : WORD;
Next : PHacPacket;
RealPost : POINTER;
RealPostDS : WORD;
OSDepLength : BYTE;
DPT : Pointer;
OSDPData : Array[1..180] of BYTE;
OSDPMyDSeg : WORD;
OSDPMyPost : Pointer;
OSDPMyIdata : Pointer;
OSDPMyAll : Pointer;
END;
PPHacPacket = ^PHacPacket;
TDefHacPacket = THacPacket;
PDefHacPacket = ^TDefHacPacket;
{-----------------------}
{ Post Procedure Syntax }
{-----------------------}
THMPostProc = Procedure( Packet : PHacPacket );
TExecSCSIPostProc = Procedure( HacError : WORD;
DevError : WORD;
IData : Pointer );
{----------------------}
{ Add Client Structure }
{----------------------}
TAddClientStructure = RECORD
AENProc : POINTER; { Seg:Ofs of clients AEN procedure }
AENAttr : WORD; { AEN types that client wants 2 C }
TypeID : WORD; { Client type ID (int13,aspi,etc) }
DSeg : WORD; { DataSeg value for AENProc call }
END;
{-----------------------------}
{ ESDefaultPostInfo Structure }
{-----------------------------}
TESDefaultPostInfo = RECORD
flagw : WORD;
HacError : WORD;
DevError : WORD;
Reserved : WORD;
END;
PESDefaultPostInfo = ^TESDefaultPostInfo;
{--------------------------}
{ HAC Manager Capabilities }
{--------------------------}
THMCaps = RECORD
Present : BOOLEAN;
MajorVer : BYTE;
MinorVer : BYTE;
MaintVer : BYTE;
CheckLevel : WORD;
LibMajorVer : BYTE;
LibMinorVer : BYTE;
LibMaintVer : BYTE;
LibCheckLevel : BYTE;
NumHacs : BYTE;
MinHPSize : WORD;
END;
PHMCaps = ^THMCaps;
{------------}
{ All Record }
{------------}
TAll = RECORD
HP : PHacPacket;
VirtIOSH : PIOSHeader;
PhysIOSH : PIOSHeader;
Data : Pointer;
Sense : Pointer;
flagw : WORD;
VIOSHE : WORD;
PIOSHE : WORD;
DataSize : LONGINT;
SenseSize : LONGINT;
END;
PAll = ^TAll;
{---------------------------------------------------------------------------}
{--------------------------------------------}
{ HAC Manager APP library specific functions }
{--------------------------------------------}
Function HM_LibInit : TError;
{ MUST BE CALLED BEFORE USING ANY OF THESE FUNCTIONS! }
Procedure HM_GetCaps( HMCaps : PHMCaps );
{ Will return capability information on the HAC manager, including }
{ version, checklevel, number of hacs, etc. etc. }
{ }
{ HMCAPS Pointer to an THMCaps structure. }
{-----------------------}
{ Hac Manager Functions }
{-----------------------}
Function HM_NewAEN( AENMask : WORD;
AENProc : POINTER ): TAENHandle;
{ Informs the HAC manager to accept a new AEN to its internal list }
{ of AENs. Any time an asyncronous event occurs, the hac mgr }
{ will see if it is a type of event that this routine wants }
{ to see by checking the AEN type against the AENMask value. If it }
{ passes the AENMask, the hac mgr will call the specified AENProc. }
{ }
{ This function returns a TAENHandle which must be used to }
{ dispose of the AEN before the AEN procedure can "Go away" }
{ (IE: Be unloaded from system memory) }
{ }
{ AENFlags Flags and mask of events this AEN proc wants }
{ to see. }
{ }
{ AENProc Pointer to the AEN procedure. }
{ }
{ [RETURNS] TAENHandle, an AEN handle. }
Procedure HM_DisposeAEN( AENHandle : TAENHandle );
{ Tells the HAC manager to unload an AEN procedure. }
{ }
{ TAENHandle An AEN Handle. }
{---}
Function HM_ExecPacket( HMPacket : PHacPacket ): TError;
{ Executes any HAC Manager packet }
{ }
{ HMPacket Pointer to a Hac Manger Packet. }
{ }
{ [RETURNS] Status/Error. }
{ 0 if successfull. }
{---}
Function HM_HACReset( HAC : BYTE ): TError;
{ Resets and Re-initializes the specified Host Adapter Channel }
{ }
{ HAC HAC to reset/Re-init }
{ }
{ [RETURNS] Status/Error. }
{ 0 if successfull. }
{---}
Function HM_BusReset( HAC : BYTE;
SCSIBus : BYTE ): TError;
{ Resets all SCSI devices on the specified specified SCSI bus of }
{ the specified HAC. }
{ }
{ HAC HAC SCSI Bus resides on }
{ SCSIBus SCSI Bus to reset }
{ }
{ [RETURNS] Status/Error. }
{ 0 if successfull. }
{---}
Function HM_DeviceReset( HAC : BYTE;
SCSIBus : BYTE;
Target : BYTE ): TError;
{ Resets a SCSI device on the specified SCSI Bus of the }
{ specified HAC. }
{ }
{ HAC HAC SCSI Bus resides on }
{ SCSIBus SCSI Bus device resides on }
{ Target Target ID of the SCSI device to reset }
{ }
{ [RETURNS] Status/Error. }
{ 0 if successfull. }
{---}
Function HM_PacketAbort( Packet : PHacPacket ): TError;
{ Aborts the specified HAC Manager packet. }
{ }
{ Packet A Hac Manager packet which was previously }
{ transmitted to the HAC manager and has not }
{ yet been executed. }
{ }
{ }
{ [RETURNS] Status/Error. }
{ 0 if successfull. }
{---}
Function HM_HDTGet( HAC : BYTE;
HDT : Pointer ): TError;
{ Gets the HAC Descriptor Table (HDT) of the specified HAC }
{ }
{ HAC HAC to get HDt from. }
{ }
{ HDT Pointer to buffer to receive a copy of the }
{ HDT. }
{ }
{ [RETURNS] Status/Error. }
{ 0 if successfull. }
{---}
Function HM_HDTSet( HAC : BYTE;
HDT : Pointer ): TError;
{ Sets the HAC Descriptor Table (HDT) of the specified HAC }
{ }
{ HAC HAC to receive new HDT. }
{ }
{ HDT Pointer to a HDT to be copied to the HACs }
{ HDT. }
{ }
{ [RETURNS] Status/Error. }
{ 0 if successfull. }
{---}
Function HM_ReqSenseBroadcast( HAC : BYTE;
SCSIBus : BYTE;
Target : BYTE;
Lun : BYTE;
ReqSense : Pointer;
ReqSenSize : WORD ): TError;
{ Broadcast Request Sense Data to all HAC Manager AEN clients }
{ }
{ HAC HAC request sense data came from. }
{ SCSIBus SCSIBus request sense data came from. }
{ TARGET Target request sense data came from. }
{ Lun Logical Unit Number Request Sense came from. }
{ }
{ ReqSense Pointer to request sense data. }
{ ReqSenSize Size of request sense data }
{ }
{ [RETURNS] Status/Error. }
{ 0 if successfull. }
{-----------------------}
{ Execute SCSI Function }
{-----------------------}
Function HM_ExecSCSI( flagw : WORD;
Target : BYTE;
Lun : BYTE;
Channel : BYTE;
SubChannel : BYTE;
CDB : PCDB;
CDBSize : BYTE;
IOBuff : Pointer;
IOSize : LONGINT;
PostAddr : Pointer;
PostDSeg : WORD;
PostIData : Pointer ): TError;
{ Will dynamically allocate the HAC packet and all other objects }
{ required to execute the SCSI command. These objects will then }
{ be filled in as specified, and the SCSI command executed. }
{ If not posting, all dynamically allocated objects will be freed }
{ prior to returning. If posting, this function will deflect }
{ the post to its own routine, which will free the dynamically }
{ allocated objects and call the specified POST }
{ routine which should expect only to get the ERROR and PostIData }
{ values on the stack (as opposed to a PHacPacket). }
{ }
{ It should be noted that this command does not support auto }
{ request sense or linked commmands. }
{ }
{ flagw }
{ }
{ ES_Write For SCSI Write operation (Host-->Devices) }
{ ES_Read For SCSI Read operation (Devices<--Host) }
{ }
{ ES_AutoDIr For SCSI Read/Write direction automatic }
{ determination. If this flag }
{ is set, the caller need not specify ES_Read }
{ or ES_Write. }
{ }
{ ES_UseIOSH Indicates that IOBuff points to an IOS hdr }
{ and not directly to an IO buffer. }
{ An IOS is like a scatter/gather list. }
{ }
{ ES_CPost To call post routine with 'C' calling }
{ convention. }
{ }
{ ES_PascalPost To call post routine with PASCAL calling }
{ convention. }
{ }
{ Channel Host Adapter Channel (HAC) to use. }
{ SubChannel HAC SCSI SubChannel to use. }
{ Target SCSI Target to use. }
{ Lun SCSI Targets LUN to use. }
{ }
{ CDB Pointer to the CDB to execute. }
{ CDBSize Length of the CDB, in bytes. }
{ }
{ IOBuff Pointer to an I/O buffer or to an IOS }
{ is the ES_UseIOSH flag is set. }
{ }
{ IOSize Number of bytes to I/O. }
{ }
{ PostAddr Pointer to a Exec SCSI Post Routine, }
{ }
{ set to 0 if not using a post routine, }
{ set to ESDefaultPost to use the default }
{ post routine. (Described later) }
{ }
{ PostDSeg Value that should be loaded into the 80x86 }
{ Data Segment register (DS) prior to }
{ calling the post routine, }
{ }
{ set to 0 if you don't care, }
{ set to ESDefaultPostDS when using the }
{ default post routine. }
{ }
{ PostIData 4 bytes of post instance data. This value }
{ will be passed on the stack as a paramater }
{ to the post routine. It can be used by }
{ post routines that are specified in }
{ multiple HM_ExecSCSI calls to identify }
{ which request is being posted. }
{ }
{ For the ESDefaultPost routine, this value }
{ should point to a an ESDefaultPostInfo }
{ structure which will be filled in by the }
{ ESDefaultPost routine during posting. }
{ Programs who wish to poll for HM_ExecSCSI }
{ completion can poll the specified }
{ ESDefaultPostInfo structure. }
{ }
{ If this value is set to 0, the }
{ ESDefaultPost routine will not fill out an }
{ ESDefaultPostInfo structure during posting. }
{------------------------------------------}
{ HAC Manager Object Construction Funtions }
{------------------------------------------}
Function HM_HacPacketAlloc( flagw : WORD ): PHacPacket;
{ Will allocate a HAC packet. All fields will be zero. }
{ This function will allocate a HAC packet plus the required }
{ number of operating system dependent bytes at the end of the }
{ packet.
{ }
{ flagw are not currently used. }
{ }
{ [RETURNS] Pointer to a HAC packet, }
{ 0/NIL if a packet could not be allocated. }
Procedure HM_HacPacketFree( HacPacket : PHacPacket );
{ Will free a HAC packet. }
{ }
{ HacPacket Pointer to a HAC packet. }
{---}
Function HM_IOSHeaderAlloc( flagw : WORD;
NumEntries : WORD ): PIOSHeader;
{ Will dynamically allocate an IOS of the default amount of IOS }
{ entries. Will also set all IOS fields to 0 }
{ }
{ flagw }
{ }
{ IOS_AllocVirt To allocate a virtual IOS. }
{ IOS_AllocPhys To allocate a physical IOS. }
{ }
{ NumEntries Number of IOS entries to allocated in the }
{ IOS, }
{ }
{ set to IOS_DefaultLen to allocate the }
{ default number of IOS entries for the }
{ specified IOS type. }
{ }
{ [RETURNS] Pointer to an IOS, or 0/nil if an IOS }
{ could not be allocated. }
Function HM_IOSAddBuff( IOSH : PIOSHeader;
BuffAddr : POINTER;
BuffSize : LONGINT ): TError;
{ Will add a buffer to the IOS allocated above. }
{ }
{ BuffAddr Pointer to the region/buffer to add. }
{ BuffSize Size of the region/buffer, in bytes. }
{ }
{ [RETURNS] 0 if no error, }
{ (error codes here) }
Function HM_IOSGetUsedCount( IOSH : PIOSHeader ): WORD;
{ Will return the number of entries in the IOS that are used. }
{ }
{ IOS Pointer to an IOS. }
{ }
{ [RETURNS] Number of used IOS entries. }
Function HM_IOSGetByteCount( IOSH : PIOSHeader ): LONGINT;
{ Will return the combined length of all the buffers in the IOS }
{ }
{ IOS Pointer to an IOS. }
{ }
{ [RETURNS] Total IOS byte count. }
Function HM_IOSGetPointer( IOSH : PIOSHeader ): Pios;
Procedure HM_IOSClear( IOSH : PIOSHeader );
{ Will clear all the buffer entries out of an IOS. }
{ }
{ IOS Pointer to an IOS. }
Procedure HM_IOSHeaderFree( IOSH : PIOSHeader );
{ Will dynamically free the IOS header. }
{ }
{ IOS Pointer to an IOS header. }
{---}
Function HM_AllAlloc( flagw : WORD;
VirtIOSLen : WORD;
PhysIOSLen : WORD;
DataLen : LONGINT;
SenseLen : WORD ): PAll;
{ Dynamically allocates a HAC packet, Physical IOS, Virutal IOS }
{ and a sense buffer. The PhysIOS, VirtIOS, Databuff and SenseBuff }
{ fields in the hac packet will point to the newly allocated }
{ structures, As will the fields in the root of the ALL record. }
{ }
{ flagw are not currently used. }
{ }
{ VirtIOSLen Number of IOS entries to allocate in the }
{ virtual IOS, }
{ }
{ set to IOS_DefaultLen to allocate default # }
{ set to 0 to not allocate a virtual IOS. }
{ }
{ PhysIOSLen Number of IOS entries to allocate in the }
{ physical IOS, }
{ }
{ set to IOS_DefaultLen to allocate default # }
{ set to 0 to not allocate a physical IOS. }
{ }
{ DataLen Size of the data buffer to allocate, }
{ set to 0 to not allocate a data buffer. }
{ }
{ SenseLen Size of the sense buffer to allocate, }
{ set to 0 to not allocat a sense buffer. }
{ }
{ [RETURNS] Pointer to a new Tall structure, }
{ or 0 if one could not be allocated. }
Procedure HM_AllFree( All : PAll );
{ Gives back everything allocated with HM_AllAlloc, above }
{ }
{ Tall Pointer to a Tall structure. }
{---------------------------------------------}
{ HAC Manager Packet Loading Helper Functions }
{---------------------------------------------}
Procedure HM_CDB6Load( CDB : PCDB;
b1 : BYTE;
b2 : BYTE;
b3 : BYTE;
b4 : BYTE;
b5 : BYTE;
b6 : BYTE );
Procedure HM_CDB10Load( CDB : PCDB;
b1 : BYTE;
b2 : BYTE;
b3 : BYTE;
b4 : BYTE;
b5 : BYTE;
b6 : BYTE;
b7 : BYTE;
b8 : BYTE;
b9 : BYTE;
b10 : BYTE );
Procedure HM_LoadHacPacket( HacPacket : PHacPacket;
Command : BYTE;
flagw : BYTE;
Target : BYTE;
LUN : BYTE;
Channel : BYTE;
SubChannel : BYTE;
DevStatus : BYTE;
HacStatus : BYTE;
CDBSize : BYTE;
CDB : PCDB;
SenseBuff : Pointer;
SenseBuffLen: WORD;
VueStatus : Pointer;
IOSize : LONGINT;
PhysElements: WORD;
PhysIOS : Pointer;
VirtElements: WORD;
VirtIOS : Pointer;
PostRoutine : Pointer;
PostDSeg : WORD;
Next : PHacPacket );